﻿using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;

namespace Pay.Core {
	/// <summary>  
	/// FTP类  
	/// </summary>  
	public class FTP {
		#region 变量声明  

		/// <summary>  
		/// 服务器连接地址  
		/// </summary>  
		public string server;

		/// <summary>  
		/// 登陆帐号  
		/// </summary>  
		public string user;

		/// <summary>  
		/// 登陆口令  
		/// </summary>  
		public string pass;

		/// <summary>  
		/// 端口号  
		/// </summary>  
		public int port;

		/// <summary>  
		/// 无响应时间（FTP在指定时间内无响应）  
		/// </summary>  
		public int timeout;

		/// <summary>  
		/// 服务器错误状态信息  
		/// </summary>  
		public string errormessage;


		/// <summary>  
		/// 服务器状态返回信息  
		/// </summary>  
		private string messages;

		/// <summary>  
		/// 服务器的响应信息  
		/// </summary>  
		private string responseStr;

		/// <summary>  
		/// 链接模式（主动或被动，默认为被动）  
		/// </summary>  
		private bool passive_mode;

		/// <summary>  
		/// 上传或下载信息字节数  
		/// </summary>  
		private long bytes_total;

		/// <summary>  
		/// 上传或下载的文件大小  
		/// </summary>  
		private long file_size;

		/// <summary>  
		/// 主套接字  
		/// </summary>  
		private Socket main_sock;

		/// <summary>  
		/// 要链接的网络地址终结点  
		/// </summary>  
		private IPEndPoint main_ipEndPoint;

		/// <summary>  
		/// 侦听套接字  
		/// </summary>  
		private Socket listening_sock;

		/// <summary>  
		/// 数据套接字  
		/// </summary>  
		private Socket data_sock;

		/// <summary>  
		/// 要链接的网络数据地址终结点  
		/// </summary>  
		private IPEndPoint data_ipEndPoint;

		/// <summary>  
		/// 用于上传或下载的文件流对象  
		/// </summary>  
		private FileStream file;

		/// <summary>  
		/// 与FTP服务器交互的状态值  
		/// </summary>  
		private int response;

		/// <summary>  
		/// 读取并保存当前命令执行后从FTP服务器端返回的数据信息  
		/// </summary>  
		private string bucket;

		#endregion

		#region 构造函数  

		/// <summary>  
		/// 构造函数  
		/// </summary>  
		public FTP() {
			server = null;
			user = null;
			pass = null;
			port = 21;
			passive_mode = true;
			main_sock = null;
			main_ipEndPoint = null;
			listening_sock = null;
			data_sock = null;
			data_ipEndPoint = null;
			file = null;
			bucket = "";
			bytes_total = 0;
			timeout = 10000;    //无响应时间为10秒  
			messages = "";
			errormessage = "";
		}

		/// <summary>  
		/// 构造函数  
		/// </summary>  
		/// <param name="server">服务器IP或名称</param>  
		/// <param name="user">登陆帐号</param>  
		/// <param name="pass">登陆口令</param>  
		public FTP(string server, string user, string pass) {
			this.server = server;
			this.user = user;
			this.pass = pass;
			port = 21;
			passive_mode = true;
			main_sock = null;
			main_ipEndPoint = null;
			listening_sock = null;
			data_sock = null;
			data_ipEndPoint = null;
			file = null;
			bucket = "";
			bytes_total = 0;
			timeout = 10000;    //无响应时间为10秒  
			messages = "";
			errormessage = "";
		}

		/// <summary>  
		/// 构造函数  
		/// </summary>  
		/// <param name="server">服务器IP或名称</param>  
		/// <param name="port">端口号</param>  
		/// <param name="user">登陆帐号</param>  
		/// <param name="pass">登陆口令</param>  
		public FTP(string server, int port, string user, string pass) {
			this.server = server;
			this.user = user;
			this.pass = pass;
			this.port = port;
			passive_mode = true;
			main_sock = null;
			main_ipEndPoint = null;
			listening_sock = null;
			data_sock = null;
			data_ipEndPoint = null;
			file = null;
			bucket = "";
			bytes_total = 0;
			timeout = 10000;    //无响应时间为10秒  
			messages = "";
			errormessage = "";
		}


		/// <summary>  
		/// 构造函数  
		/// </summary>  
		/// <param name="server">服务器IP或名称</param>  
		/// <param name="port">端口号</param>  
		/// <param name="user">登陆帐号</param>  
		/// <param name="pass">登陆口令</param>  
		/// <param name="mode">链接方式</param>  
		public FTP(string server, int port, string user, string pass, int mode) {
			this.server = server;
			this.user = user;
			this.pass = pass;
			this.port = port;
			passive_mode = mode <= 1 ? true : false;
			main_sock = null;
			main_ipEndPoint = null;
			listening_sock = null;
			data_sock = null;
			data_ipEndPoint = null;
			file = null;
			bucket = "";
			bytes_total = 0;
			this.timeout = 10000;    //无响应时间为10秒  
			messages = "";
			errormessage = "";
		}

		/// <summary>  
		/// 构造函数  
		/// </summary>  
		/// <param name="server">服务器IP或名称</param>  
		/// <param name="port">端口号</param>  
		/// <param name="user">登陆帐号</param>  
		/// <param name="pass">登陆口令</param>  
		/// <param name="mode">链接方式</param>  
		/// <param name="timeout">无响应时间(限时),单位:秒 (小于或等于0为不受时间限制)</param>  
		public FTP(string server, int port, string user, string pass, int mode, int timeout_sec) {
			this.server = server;
			this.user = user;
			this.pass = pass;
			this.port = port;
			passive_mode = mode <= 1 ? true : false;
			main_sock = null;
			main_ipEndPoint = null;
			listening_sock = null;
			data_sock = null;
			data_ipEndPoint = null;
			file = null;
			bucket = "";
			bytes_total = 0;
			this.timeout = (timeout_sec <= 0) ? int.MaxValue : (timeout_sec * 1000);    //无响应时间  
			messages = "";
			errormessage = "";
		}

		#endregion

		#region 属性  
		/// <summary>  
		/// 当前是否已连接  
		/// </summary>  
		public bool IsConnected {
			get {
				if (main_sock != null)
					return main_sock.Connected;
				return false;
			}
		}

		/// <summary>  
		/// 当message缓冲区有数据则返回  
		/// </summary>  
		public bool MessagesAvailable {
			get {
				if (messages.Length > 0)
					return true;
				return false;
			}
		}

		/// <summary>  
		/// 获取服务器状态返回信息, 并清空messages变量  
		/// </summary>  
		public string Messages {
			get {
				string tmp = messages;
				messages = "";
				return tmp;
			}
		}
		/// <summary>  
		/// 最新指令发出后服务器的响应  
		/// </summary>  
		public string ResponseString {
			get {
				return responseStr;
			}
		}


		/// <summary>  
		///在一次传输中,发送或接收的字节数  
		/// </summary>  
		public long BytesTotal {
			get {
				return bytes_total;
			}
		}

		/// <summary>  
		///被下载或上传的文件大小,当文件大小无效时为0  
		/// </summary>  
		public long FileSize {
			get {
				return file_size;
			}
		}

		/// <summary>  
		/// 链接模式:   
		/// true 被动模式 [默认]  
		/// false: 主动模式  
		/// </summary>  
		public bool PassiveMode {
			get {
				return passive_mode;
			}
			set {
				passive_mode = value;
			}
		}

		#endregion

		#region 操作  

		/// <summary>  
		/// 操作失败  
		/// </summary>  
		private void Fail() {
			Disconnect();
			errormessage += responseStr;
			//throw new Exception(responseStr);  
		}

		/// <summary>  
		/// 下载文件类型  
		/// </summary>  
		/// <param name="mode">true:二进制文件 false:字符文件</param>  
		private void SetBinaryMode(bool mode) {
			if (mode)
				SendCommand("TYPE I");
			else
				SendCommand("TYPE A");

			ReadResponse();
			if (response != 200)
				Fail();
		}

		/// <summary>  
		/// 发送命令  
		/// </summary>  
		/// <param name="command"></param>  
		private void SendCommand(string command) {
			Byte[] cmd = Encoding.Default.GetBytes((command + "\r\n").ToCharArray());

			if (command.Length > 3 && command.Substring(0, 4) == "PASS") {
				messages = "\rPASS xxx";
			} else {
				messages = "\r" + command;
			}

			try {
				main_sock.Send(cmd, cmd.Length, 0);
			} catch (Exception ex) {
				try {
					Disconnect();
					errormessage += ex.Message;
					return;
				} catch {
					main_sock.Close();
					file.Close();
					main_sock = null;
					main_ipEndPoint = null;
					file = null;
				}
			}
		}


		private void FillBucket() {
			Byte[] bytes = new Byte[512];
			long bytesgot;
			int msecs_passed = 0;

			while (main_sock.Available < 1) {
				System.Threading.Thread.Sleep(50);
				msecs_passed += 50;
				//当等待时间到,则断开链接  
				if (msecs_passed > timeout) {
					Disconnect();
					errormessage += "Timed out waiting on server to respond.";
					return;
				}
			}

			while (main_sock.Available > 0) {
				bytesgot = main_sock.Receive(bytes, 512, 0);
				bucket += Encoding.Default.GetString(bytes, 0, (int)bytesgot);
				System.Threading.Thread.Sleep(50);
			}
		}


		private string GetLineFromBucket() {
			int i;
			string buf = "";

			if ((i = bucket.IndexOf('\n')) < 0) {
				while (i < 0) {
					FillBucket();
					i = bucket.IndexOf('\n');
				}
			}

			buf = bucket.Substring(0, i);
			bucket = bucket.Substring(i + 1);

			return buf;
		}


		/// <summary>  
		/// 返回服务器端返回信息  
		/// </summary>  
		private void ReadResponse() {
			string buf;
			messages = "";

			while (true) {
				buf = GetLineFromBucket();

				if (Regex.Match(buf, "^[0-9]+ ").Success) {
					responseStr = buf;
					response = int.Parse(buf.Substring(0, 3));
					break;
				} else
					messages += Regex.Replace(buf, "^[0-9]+-", "") + "\n";
			}
		}


		/// <summary>  
		/// 打开数据套接字  
		/// </summary>  
		private void OpenDataSocket() {
			if (passive_mode) {
				string[] pasv;
				string server;
				int port;

				Connect();
				SendCommand("PASV");
				ReadResponse();
				if (response != 227)
					Fail();

				try {
					int i1, i2;

					i1 = responseStr.IndexOf('(') + 1;
					i2 = responseStr.IndexOf(')') - i1;
					pasv = responseStr.Substring(i1, i2).Split(',');
				} catch (Exception) {
					Disconnect();
					errormessage += "Malformed PASV response: " + responseStr;
					return;
				}

				if (pasv.Length < 6) {
					Disconnect();
					errormessage += "Malformed PASV response: " + responseStr;
					return;
				}

				server = String.Format("{0}.{1}.{2}.{3}", pasv[0], pasv[1], pasv[2], pasv[3]);
				port = (int.Parse(pasv[4]) << 8) + int.Parse(pasv[5]);

				try {
					CloseDataSocket();

					data_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

#if NET1
                    data_ipEndPoint = new IPEndPoint(Dns.GetHostByName(server).AddressList[0], port);  
#else
					data_ipEndPoint = new IPEndPoint(System.Net.Dns.GetHostEntry(server).AddressList[0], port);
#endif

					data_sock.Connect(data_ipEndPoint);

				} catch (Exception ex) {
					errormessage += "Failed to connect for data transfer: " + ex.Message;
					return;
				}
			} else {
				Connect();

				try {
					CloseDataSocket();

					listening_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

					// 对于端口,则发送IP地址.下面则提取相应信息  
					string sLocAddr = main_sock.LocalEndPoint.ToString();
					int ix = sLocAddr.IndexOf(':');
					if (ix < 0) {
						errormessage += "Failed to parse the local address: " + sLocAddr;
						return;
					}
					string sIPAddr = sLocAddr.Substring(0, ix);
					// 系统自动绑定一个端口号(设置 port = 0)  
					System.Net.IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(sIPAddr), 0);

					listening_sock.Bind(localEP);
					sLocAddr = listening_sock.LocalEndPoint.ToString();
					ix = sLocAddr.IndexOf(':');
					if (ix < 0) {
						errormessage += "Failed to parse the local address: " + sLocAddr;

					}
					int nPort = int.Parse(sLocAddr.Substring(ix + 1));

					// 开始侦听链接请求  
					listening_sock.Listen(1);
					string sPortCmd = string.Format("PORT {0},{1},{2}",
													sIPAddr.Replace('.', ','),
													nPort / 256, nPort % 256);
					SendCommand(sPortCmd);
					ReadResponse();
					if (response != 200)
						Fail();
				} catch (Exception ex) {
					errormessage += "Failed to connect for data transfer: " + ex.Message;
					return;
				}
			}
		}


		private void ConnectDataSocket() {
			if (data_sock != null)        // 已链接  
				return;

			try {
				data_sock = listening_sock.Accept();    // Accept is blocking  
				listening_sock.Close();
				listening_sock = null;

				if (data_sock == null) {
					throw new Exception("Winsock error: " +
						Convert.ToString(System.Runtime.InteropServices.Marshal.GetLastWin32Error()));
				}
			} catch (Exception ex) {
				errormessage += "Failed to connect for data transfer: " + ex.Message;
			}
		}


		private void CloseDataSocket() {
			if (data_sock != null) {
				if (data_sock.Connected) {
					data_sock.Close();
				}
				data_sock = null;
			}

			data_ipEndPoint = null;
		}

		/// <summary>  
		/// 关闭所有链接  
		/// </summary>  
		public void Disconnect() {
			CloseDataSocket();

			if (main_sock != null) {
				if (main_sock.Connected) {
					SendCommand("QUIT");
					main_sock.Close();
				}
				main_sock = null;
			}

			if (file != null)
				file.Close();

			main_ipEndPoint = null;
			file = null;
		}

		/// <summary>  
		/// 链接到FTP服务器  
		/// </summary>  
		/// <param name="server">要链接的IP地址或主机名</param>  
		/// <param name="port">端口号</param>  
		/// <param name="user">登陆帐号</param>  
		/// <param name="pass">登陆口令</param>  
		public void Connect(string server, int port, string user, string pass) {
			this.server = server;
			this.user = user;
			this.pass = pass;
			this.port = port;

			Connect();
		}

		/// <summary>  
		/// 链接到FTP服务器  
		/// </summary>  
		/// <param name="server">要链接的IP地址或主机名</param>  
		/// <param name="user">登陆帐号</param>  
		/// <param name="pass">登陆口令</param>  
		public void Connect(string server, string user, string pass) {
			this.server = server;
			this.user = user;
			this.pass = pass;

			Connect();
		}

		/// <summary>  
		/// 链接到FTP服务器  
		/// </summary>  
		public bool Connect() {
			if (server == null) {
				errormessage += "No server has been set.\r\n";
			}
			if (user == null) {
				errormessage += "No server has been set.\r\n";
			}

			if (main_sock != null)
				if (main_sock.Connected)
					return true;

			try {
				main_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
#if NET1
                main_ipEndPoint = new IPEndPoint(Dns.GetHostByName(server).AddressList[0], port);  
#else
				main_ipEndPoint = new IPEndPoint(System.Net.Dns.GetHostEntry(server).AddressList[0], port);
#endif

				main_sock.Connect(main_ipEndPoint);
			} catch (Exception ex) {
				errormessage += ex.Message;
				return false;
			}

			ReadResponse();
			if (response != 220)
				Fail();

			SendCommand("USER " + user);
			ReadResponse();

			switch (response) {
				case 331:
					if (pass == null) {
						Disconnect();
						errormessage += "No password has been set.";
						return false;
					}
					SendCommand("PASS " + pass);
					ReadResponse();
					if (response != 230) {
						Fail();
						return false;
					}
					break;
				case 230:
					break;
			}

			return true;
		}

		/// <summary>  
		/// 获取FTP当前(工作)目录下的文件列表  
		/// </summary>  
		/// <returns>返回文件列表数组</returns>  
		public ArrayList List() {
			Byte[] bytes = new Byte[512];
			string file_list = "";
			long bytesgot = 0;
			int msecs_passed = 0;
			ArrayList list = new ArrayList();

			Connect();
			OpenDataSocket();
			SendCommand("LIST");
			ReadResponse();

			switch (response) {
				case 125:
				case 150:
					break;
				default:
					CloseDataSocket();
					throw new Exception(responseStr);
			}
			ConnectDataSocket();

			while (data_sock.Available < 1) {
				System.Threading.Thread.Sleep(50);
				msecs_passed += 50;

				if (msecs_passed > (timeout / 10)) {
					break;
				}
			}

			while (data_sock.Available > 0) {
				bytesgot = data_sock.Receive(bytes, bytes.Length, 0);
				//file_list += Encoding.ASCII.GetString(bytes, 0, (int) bytesgot);  
				file_list += Encoding.Default.GetString(bytes, 0, (int)bytesgot);
				System.Threading.Thread.Sleep(50);
			}

			CloseDataSocket();

			ReadResponse();
			if (response != 226)
				throw new Exception(responseStr);

			foreach (string f in file_list.Split('\n')) {
				if (f.Length > 0 && !Regex.Match(f, "^total").Success)
					list.Add(f.Substring(0, f.Length - 1));
			}

			return list;
		}

		/// <summary>  
		/// 获取到文件名列表  
		/// </summary>  
		/// <returns>返回文件名列表</returns>  
		public ArrayList ListFiles() {
			ArrayList list = new ArrayList();

			foreach (string f in List()) {
				if ((f.Length > 0)) {
					if ((f[0] != 'd') && (f.ToUpper().IndexOf("<DIR>") < 0))
						list.Add(f);
				}
			}

			return list;
		}

		/// <summary>  
		/// 获取路径列表  
		/// </summary>  
		/// <returns>返回路径列表</returns>  
		public ArrayList ListDirectories() {
			ArrayList list = new ArrayList();

			foreach (string f in List()) {
				if (f.Length > 0) {
					if ((f[0] == 'd') || (f.ToUpper().IndexOf("<DIR>") >= 0))
						list.Add(f);
				}
			}

			return list;
		}

		/// <summary>  
		/// 获取原始数据信息.  
		/// </summary>  
		/// <param name="fileName">远程文件名</param>  
		/// <returns>返回原始数据信息.</returns>  
		public string GetFileDateRaw(string fileName) {
			Connect();

			SendCommand("MDTM " + fileName);
			ReadResponse();
			if (response != 213) {
				errormessage += responseStr;
				return "";
			}

			return (this.responseStr.Substring(4));
		}

		/// <summary>  
		/// 得到文件日期.  
		/// </summary>  
		/// <param name="fileName">远程文件名</param>  
		/// <returns>返回远程文件日期</returns>  
		public DateTime GetFileDate(string fileName) {
			return ConvertFTPDateToDateTime(GetFileDateRaw(fileName));
		}

		private DateTime ConvertFTPDateToDateTime(string input) {
			if (input.Length < 14)
				throw new ArgumentException("Input Value for ConvertFTPDateToDateTime method was too short.");

			//YYYYMMDDhhmmss":   
			int year = Convert.ToInt16(input.Substring(0, 4));
			int month = Convert.ToInt16(input.Substring(4, 2));
			int day = Convert.ToInt16(input.Substring(6, 2));
			int hour = Convert.ToInt16(input.Substring(8, 2));
			int min = Convert.ToInt16(input.Substring(10, 2));
			int sec = Convert.ToInt16(input.Substring(12, 2));

			return new DateTime(year, month, day, hour, min, sec);
		}

		/// <summary>  
		/// 获取FTP上的当前(工作)路径  
		/// </summary>  
		/// <returns>返回FTP上的当前(工作)路径</returns>  
		public string GetWorkingDirectory() {
			//PWD - 显示工作路径  
			Connect();
			SendCommand("PWD");
			ReadResponse();

			if (response != 257) {
				errormessage += responseStr;
			}

			string pwd;
			try {
				pwd = responseStr.Substring(responseStr.IndexOf("\"", 0) + 1);//5);  
				pwd = pwd.Substring(0, pwd.LastIndexOf("\""));
				pwd = pwd.Replace("\"\"", "\""); // 替换带引号的路径信息符号  
			} catch (Exception ex) {
				errormessage += ex.Message;
				return null;
			}

			return pwd;
		}


		/// <summary>  
		/// 跳转服务器上的当前(工作)路径  
		/// </summary>  
		/// <param name="path">要跳转的路径</param>  
		public bool ChangeDir(string path) {
			Connect();
			SendCommand("CWD " + path);
			ReadResponse();
			if (response != 250) {
				errormessage += responseStr;
				return false;
			}
			return true;
		}

		/// <summary>  
		/// 创建指定的目录  
		/// </summary>  
		/// <param name="dir">要创建的目录</param>  
		public void MakeDir(string dir) {
			Connect();
			SendCommand("MKD " + dir);
			ReadResponse();

			switch (response) {
				case 257:
				case 250:
					break;
				default: {
						errormessage += responseStr;
						break;
					}
			}
		}

		/// <summary>  
		/// 移除FTP上的指定目录  
		/// </summary>  
		/// <param name="dir">要移除的目录</param>  
		public void RemoveDir(string dir) {
			Connect();
			SendCommand("RMD " + dir);
			ReadResponse();
			if (response != 250) {
				errormessage += responseStr;
				return;
				;
			}
		}

		/// <summary>  
		/// 移除FTP上的指定文件  
		/// </summary>  
		/// <param name="filename">要移除的文件名称</param>  
		public void RemoveFile(string filename) {
			Connect();
			SendCommand("DELE " + filename);
			ReadResponse();
			if (response != 250) {
				errormessage += responseStr;
			}
		}

		/// <summary>  
		/// 重命名FTP上的文件  
		/// </summary>  
		/// <param name="oldfilename">原文件名</param>  
		/// <param name="newfilename">新文件名</param>  
		public void RenameFile(string oldfilename, string newfilename) {
			Connect();
			SendCommand("RNFR " + oldfilename);
			ReadResponse();
			if (response != 350) {
				errormessage += responseStr;
			} else {
				SendCommand("RNTO " + newfilename);
				ReadResponse();
				if (response != 250) {
					errormessage += responseStr;
				}
			}
		}

		/// <summary>  
		/// 获得指定文件的大小(如果FTP支持)  
		/// </summary>  
		/// <param name="filename">指定的文件</param>  
		/// <returns>返回指定文件的大小</returns>  
		public long GetFileSize(string filename) {
			Connect();
			SendCommand("SIZE " + filename);
			ReadResponse();
			if (response != 213) {
				errormessage += responseStr;
				return 0;
			}

			return Int64.Parse(responseStr.Substring(4));
		}

		/// <summary>  
		/// 上传指定的文件  
		/// </summary>  
		/// <param name="filename">要上传的文件</param>  
		public bool OpenUpload(string filename) {
			return OpenUpload(filename, filename, false);
		}

		/// <summary>  
		/// 上传指定的文件  
		/// </summary>  
		/// <param name="filename">本地文件名</param>  
		/// <param name="remotefilename">远程要覆盖的文件名</param>  
		public bool OpenUpload(string filename, string remotefilename) {
			return OpenUpload(filename, remotefilename, false);
		}

		/// <summary>  
		/// 上传指定的文件  
		/// </summary>  
		/// <param name="filename">本地文件名</param>  
		/// <param name="resume">如果存在,则尝试恢复</param>  
		public bool OpenUpload(string filename, bool resume) {
			return OpenUpload(filename, filename, resume);
		}

		/// <summary>  
		/// 上传指定的文件  
		/// </summary>  
		/// <param name="filename">本地文件名</param>  
		/// <param name="remote_filename">远程要覆盖的文件名</param>  
		/// <param name="resume">如果存在,则尝试恢复</param>  
		public bool OpenUpload(string filename, string remote_filename, bool resume) {
			Connect();
			SetBinaryMode(true);
			OpenDataSocket();

			bytes_total = 0;

			try {
				file = new FileStream(filename, FileMode.Open);
			} catch (Exception ex) {
				file = null;
				errormessage += ex.Message;
				return false;
			}

			file_size = file.Length;

			if (resume) {
				long size = GetFileSize(remote_filename);
				if (size == 0)
					errormessage = "";
				SendCommand("REST " + size);
				ReadResponse();
				if (response == 350)
					file.Seek(size, SeekOrigin.Begin);
			}

			SendCommand("STOR " + remote_filename);
			ReadResponse();

			switch (response) {
				case 125:
				case 150:
					break;
				default:
					file.Close();
					file = null;
					errormessage += responseStr;
					return false;
			}
			ConnectDataSocket();

			return true;
		}

		/// <summary>  
		/// 下载指定文件  
		/// </summary>  
		/// <param name="filename">远程文件名称</param>  
		public void OpenDownload(string filename) {
			OpenDownload(filename, filename, false);
		}

		/// <summary>  
		/// 下载并恢复指定文件  
		/// </summary>  
		/// <param name="filename">远程文件名称</param>  
		/// <param name="resume">如文件存在,则尝试恢复</param>  
		public void OpenDownload(string filename, bool resume) {
			OpenDownload(filename, filename, resume);
		}

		/// <summary>  
		/// 下载指定文件  
		/// </summary>  
		/// <param name="remote_filename">远程文件名称</param>  
		/// <param name="localfilename">本地文件名</param>  
		public void OpenDownload(string remote_filename, string localfilename) {
			OpenDownload(remote_filename, localfilename, false);
		}

		/// <summary>  
		/// 打开并下载文件  
		/// </summary>  
		/// <param name="remote_filename">远程文件名称</param>  
		/// <param name="local_filename">本地文件名</param>  
		/// <param name="resume">如果文件存在则恢复</param>  
		public void OpenDownload(string remote_filename, string local_filename, bool resume) {
			Connect();
			SetBinaryMode(true);

			bytes_total = 0;

			try {
				file_size = GetFileSize(remote_filename);
			} catch {
				file_size = 0;
			}

			if (resume && File.Exists(local_filename)) {
				try {
					file = new FileStream(local_filename, FileMode.Open);
				} catch (Exception ex) {
					file = null;
					throw new Exception(ex.Message);
				}

				SendCommand("REST " + file.Length);
				ReadResponse();
				if (response != 350)
					throw new Exception(responseStr);
				file.Seek(file.Length, SeekOrigin.Begin);
				bytes_total = file.Length;
			} else {
				try {
					file = new FileStream(local_filename, FileMode.Create);
				} catch (Exception ex) {
					file = null;
					throw new Exception(ex.Message);
				}
			}

			OpenDataSocket();
			SendCommand("RETR " + remote_filename);
			ReadResponse();

			switch (response) {
				case 125:
				case 150:
					break;
				default:
					file.Close();
					file = null;
					errormessage += responseStr;
					return;
			}
			ConnectDataSocket();

			return;
		}

		/// <summary>  
		/// 上传文件(循环调用直到上传完毕)  
		/// </summary>  
		/// <returns>发送的字节数</returns>  
		public long DoUpload() {
			Byte[] bytes = new Byte[512];
			long bytes_got;

			try {
				bytes_got = file.Read(bytes, 0, bytes.Length);
				bytes_total += bytes_got;
				data_sock.Send(bytes, (int)bytes_got, 0);

				if (bytes_got <= 0) {
					//上传完毕或有错误发生  
					file.Close();
					file = null;

					CloseDataSocket();
					ReadResponse();
					switch (response) {
						case 226:
						case 250:
							break;
						default: //当上传中断时  
							{
								errormessage += responseStr;
								return -1;
							}
					}

					SetBinaryMode(false);
				}
			} catch (Exception ex) {
				file.Close();
				file = null;
				CloseDataSocket();
				ReadResponse();
				SetBinaryMode(false);
				//throw ex;  
				//当上传中断时  
				errormessage += ex.Message;
				return -1;
			}

			return bytes_got;
		}

		/// <summary>  
		/// 下载文件(循环调用直到下载完毕)  
		/// </summary>  
		/// <returns>接收到的字节点</returns>  
		public long DoDownload() {
			Byte[] bytes = new Byte[512];
			long bytes_got;

			try {
				bytes_got = data_sock.Receive(bytes, bytes.Length, 0);

				if (bytes_got <= 0) {
					//下载完毕或有错误发生  
					CloseDataSocket();
					file.Close();
					file = null;

					ReadResponse();
					switch (response) {
						case 226:
						case 250:
							break;
						default: {
								errormessage += responseStr;
								return -1;
							}
					}

					//SetBinaryMode(false);  
					SetBinaryMode(true);//业务需要，使用二进制模式下载  
					return bytes_got;
				}

				file.Write(bytes, 0, (int)bytes_got);
				bytes_total += bytes_got;
			} catch (Exception ex) {
				CloseDataSocket();
				file.Close();
				file = null;
				ReadResponse();
				SetBinaryMode(false);
				//throw ex;  
				//当下载中断时  
				errormessage += ex.Message;
				return -1;
			}

			return bytes_got;
		}

		#endregion
	}
}
